package litegame

import (
	//"corelib/db"
	"corelib/log"
	"corelib/utils"
	"crypto/hmac"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	//"library/DoDB"
	"net/http"
	"os"
	"sort"
	"strings"
)

var (
	liteGameHelperIns *LiteGameHelper
)

type BaseErrRet struct {
	Errmsg  string `json:"errmsg"`  // 错误信息
	Errcode int32  `json:"errcode"` // 错误码
}

type LiteGameHelper struct {
	mAppID     string
	mAppSecret string
	mAppKey    string
	mAppPayID  string
	cacheRedis string
}

func CreateHelper(appID, appSecret, appKey, payID, cacheRedis string) *LiteGameHelper {
	return &LiteGameHelper{
		mAppID:     appID,
		mAppSecret: appSecret,
		mAppKey:    appKey,
		mAppPayID:  payID,
		cacheRedis: cacheRedis,
	}
}

func SetLiteGameHelper(l *LiteGameHelper) {
	liteGameHelperIns = l
}

func InitLiteGameHelper(cacheRedis string) *LiteGameHelper {
	tAppID := os.Getenv("WECHAT_APPID")
	tAppSecret := os.Getenv("WECHAT_APPSECRET")
	tAppKey := os.Getenv("WECHAT_APPKEY")
	tAppPayID := os.Getenv("WECHAT_PAYID")
	tSandBox := os.Getenv("WECHAT_SANDBOX")
	log.Debug("WECHAT_APPID=", tAppID)
	log.Debug("WECHAT_APPSECRET=", tAppSecret)
	log.Debug("WECHAT_APPKEY=", tAppKey)
	log.Debug("WECHAT_PAYID=", tAppPayID)
	log.Debug("WECHAT_SANDBOX=", tSandBox)
	liteGameHelperIns = CreateHelper(tAppID, tAppSecret, tAppKey, tAppPayID, cacheRedis)
	return liteGameHelperIns
}

func (l *LiteGameHelper) Code2session(code string) (*WechatSession, error) {
	return code2Session(l.mAppID, l.mAppSecret, code)
}

func (l *LiteGameHelper) GetOfferId() string {
	return l.mAppPayID
}

func (l *LiteGameHelper) GetAppkey() string {
	return l.mAppKey
}

func (l *LiteGameHelper) GetAccessToken() string {
	if l.cacheRedis != "" {
		//suc, ret := DoDB.DO_REDIS(l.cacheRedis, db.REDIS_OPT_GET, "WECHAT_ACCESS_TOKEN", nil, 0, false)
		//if suc {
		//	if val, ok := ret.Ret.(string); ok {
		//		if val != "" {
		//			return val
		//		}
		//	}
		//}
	}
	wxRet, err := getWxAccessToken(l.mAppID, l.mAppSecret)
	if err != nil {
		log.Error("GetAccessToken", map[string]interface{}{"err": err})
		panic(err)
	}
	if l.cacheRedis != "" {
		//DoDB.DO_REDIS(l.cacheRedis, db.REDIS_OPT_SET, "WECHAT_ACCESS_TOKEN", wxRet.AccessToken, int32(wxRet.ExpiresIn-10), true)
	}
	return wxRet.AccessToken
}

func HmacSha256(key, data string) string {
	keys := []byte(key)
	h := hmac.New(sha256.New, keys)
	h.Write([]byte(data))
	return hex.EncodeToString(h.Sum(nil))
}

func Sha1(data string) string {
	h := sha1.New()
	h.Write([]byte(data))
	return hex.EncodeToString(h.Sum(nil))
}

func MD5(data string) string {
	has := md5.Sum([]byte(data))
	return hex.EncodeToString(has[:])
}

func GetBalance(openid, userip, signature string) (*WxPayGetBalanceRet, error) {
	return getWxPayBalance(liteGameHelperIns, openid, userip, signature)
}

func Pay(openid, userip, signature string, amount int, tradeNo string) (*WxPayResultRet, error) {
	return doWxPay(liteGameHelperIns, openid, userip, signature, amount, tradeNo)
}

// 虚拟支付1.0
func GetBalanceV10(openid, userip, signature string) (*WxPayGetBalanceRet, error) {
	sandbox := "sandbox/"
	if os.Getenv("WECHAT_SANDBOX") == "0" {
		sandbox = ""
	}
	addr := "https://api.weixin.qq.com/cgi-bin/midas/%sgetbalance?access_token=%s"
	accessToken := liteGameHelperIns.GetAccessToken()
	data := map[string]interface{}{
		"openid":   openid,
		"appid":    liteGameHelperIns.mAppID,
		"offer_id": liteGameHelperIns.mAppPayID,
		"ts":       utils.GetNowTs(),
		"zone_id":  "1",
		"pf":       "android",
		//"sig":      "",
		//"env":      1,
		//"user_ip":  userip,
	}
	strSingTemp := ksort2JoinStr(data, "&") + fmt.Sprintf("&org_loc=/cgi-bin/midas/%sgetbalance&method=POST&secret=%s", sandbox, liteGameHelperIns.mAppKey)
	sig := HmacSha256(liteGameHelperIns.mAppKey, strSingTemp)
	data["sig"] = sig
	postBody, _ := json.Marshal(data)
	err, httpStatus, resp := httpPost(fmt.Sprintf(addr, sandbox, accessToken), postBody)
	if httpStatus != http.StatusOK {
		return nil, fmt.Errorf("getWxPayBalance失败 httpStatus=%d", httpStatus)
	}
	ret := &WxPayGetBalanceRet{}
	err = json.Unmarshal(resp, &ret)
	if err != nil {
		return nil, fmt.Errorf("getWxPayBalance解析失败 err=%s", err)
	}
	return ret, nil
}

func PayV10(openid, userip, signature string, amount int, tradeNo string) (*WxPayResultRet, error) {
	sandbox := "sandbox/"
	if os.Getenv("WECHAT_SANDBOX") == "0" {
		sandbox = ""
	}
	addr := "https://api.weixin.qq.com/cgi-bin/midas/%spay?access_token=%s"
	accessToken := liteGameHelperIns.GetAccessToken()
	//accessToken := "84_Q8Bxf9qVAwrGSqGXMp4M6MK18GkWGvW521m6izKmJyS8VwzrNUklb9flCdKxdQDO9c4Cb-tDH7L1wy8_wyvy7JCl7Nkp7j6Nc2lDgcYxSWkinSX6CqHRrpmGg5kUSMaAFAMKE"
	data := map[string]interface{}{
		"openid":   openid,
		"appid":    liteGameHelperIns.mAppID,
		"offer_id": liteGameHelperIns.mAppPayID,
		"ts":       utils.GetNowTs(),
		"zone_id":  "1",
		"pf":       "android",
		//"user_ip":	userip,
		"amt":     amount,
		"bill_no": tradeNo,
		//"sig":      "",
		//"env":      1,
		//"user_ip":  userip,
	}
	strSingTemp := ksort2JoinStr(data, "&") + fmt.Sprintf("&org_loc=/cgi-bin/midas/%spay&method=POST&secret=%s", sandbox, liteGameHelperIns.mAppKey)
	sig := HmacSha256(liteGameHelperIns.mAppKey, strSingTemp)
	data["sig"] = sig
	postBody, _ := json.Marshal(data)
	err, httpStatus, resp := httpPost(fmt.Sprintf(addr, sandbox, accessToken), postBody)
	if httpStatus != http.StatusOK {
		return nil, fmt.Errorf("doWxPay失败 httpStatus=%d", httpStatus)
	}
	ret := &WxPayResultRet{}
	err = json.Unmarshal(resp, &ret)
	if err != nil {
		return nil, fmt.Errorf("doWxPay解析失败 err=%s", err)
	}
	return ret, nil
}

func ksort2JoinStr(m map[string]interface{}, sep string) string {
	params := make([]string, 0)
	for k, v := range m {
		params = append(params, fmt.Sprintf("%s=%v", k, v))
	}
	sort.Strings(params)
	return strings.Join(params, sep)
}
